use datasource_connector::connector::SimpleDataSourceConnector;
use datasource_connector::restful::{
    batch_instance_delete, batch_instance_insert, batch_instance_query, batch_instance_update,
    get_instance, get_instance_by_id, get_instances, instance_count, instance_delete,
    post_instance, put_instance, put_instance_by_keys,
};
use model_graph_types::container::context::Context;
use model_graph_types::modeling::system_meta_database;
use std::sync::Arc;
use std::{collections::HashMap, sync::Mutex};
use tauri::{command, AppHandle, Runtime, State, Window};

use crate::handlers::ContextState;
use crate::handlers::Result;

use model_graph_types::{
    database::DataSource,
    datasource::{
        DataSourceConnector, DeleteCondition, DeleteOptions, InsertOptions, QueryCondition,
        QueryExtention, QueryOptions, UpdateCondition, UpdateOptions,
    },
    modeling::{PagingResponse, Value},
};

async fn _get_datasources(
    context: &Arc<Mutex<Context>>,
    ds_id: u32,
    datasource: Option<DataSource>,
) -> anyhow::Result<(DataSource, DataSource)> {
    //
    let meta_datasource = system_meta_database()?;

    if ds_id > 0 {
        let datasource = SimpleDataSourceConnector::default()
            .datasource(&Some(meta_datasource.clone()), ds_id)
            .await?;
        Ok((meta_datasource, datasource))
    } else {
        if let Some(ds) = datasource {
            Ok((meta_datasource, ds))
        } else {
            Ok((meta_datasource.clone(), meta_datasource.clone()))
        }
    }
}

#[command]
pub async fn ds_find_one_by_id<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    id: String,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let instance = get_instance_by_id(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        &id,
    )
    .await?;

    Ok(instance)
}

#[command]
pub async fn ds_find_one<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    conditions: QueryCondition,
    extentions: Option<QueryExtention>,
    options: Option<QueryOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let instance = get_instance(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        conditions,
        extentions,
        options,
    )
    .await?;

    Ok(instance)
}

#[command]
pub async fn ds_find<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    conditions: QueryCondition,
    extentions: Option<QueryExtention>,
    options: Option<QueryOptions>,
) -> Result<PagingResponse<Vec<serde_json::Value>>> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = get_instances(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        conditions,
        extentions,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_count<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    conditions: QueryCondition,
    options: Option<QueryOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = instance_count(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        conditions,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_insert<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    values: HashMap<String, serde_json::Value>,
    options: Option<InsertOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = post_instance(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        values,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_update<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    conditions: UpdateCondition,
    values: HashMap<String, serde_json::Value>,
    options: Option<UpdateOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = put_instance(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        conditions,
        values,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_update_by_keys<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    keys: Vec<String>,
    values: HashMap<String, serde_json::Value>,
    options: Option<UpdateOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = put_instance_by_keys(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        keys,
        values,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_delete<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    class_identifier: String,
    conditions: DeleteCondition,
    options: Option<DeleteOptions>,
) -> Result<serde_json::Value> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res = instance_delete(
        context,
        &Some(meta_datasource),
        &datasource,
        &class_identifier,
        conditions,
        options,
    )
    .await?;

    Ok(res)
}

#[command]
pub async fn ds_batch_delete<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    items: Vec<(String, DeleteCondition)>,
    options: Option<DeleteOptions>,
) -> Result<Vec<serde_json::Value>> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res =
        batch_instance_delete(context, &Some(meta_datasource), &datasource, items, options).await?;

    Ok(res)
}

#[command]
pub async fn ds_batch_update<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    items: Vec<(String, UpdateCondition, HashMap<String, serde_json::Value>)>,
    options: Option<UpdateOptions>,
) -> Result<Vec<serde_json::Value>> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let dso = Some(meta_datasource.clone());

    let mut result: Vec<serde_json::Value> = vec![];
    for (s, c, v) in items {
        result.push(put_instance(context.clone(), &dso, &datasource, &s, c, v, options.clone()).await?);
    }
    Ok(result)
}

#[command]
pub async fn ds_batch_insert<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    items: Vec<(String, HashMap<String, serde_json::Value>)>,
    options: Option<InsertOptions>,
) -> Result<Vec<serde_json::Value>> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;

    let meta_ds_options = Some(meta_datasource.clone());
    let mut result: Vec<serde_json::Value> = vec![];
    for (s, c) in items {
        result.push(
            post_instance(context.clone(), &meta_ds_options, &datasource, &s, c, options.clone()).await?,
        );
    }
    Ok(result)
}

#[command]
pub async fn ds_batch_query<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    ds_id: u32,
    datasource: Option<DataSource>,
    items: Vec<(String, QueryCondition, Option<QueryExtention>)>,
    options: Option<QueryOptions>,
) -> Result<Vec<PagingResponse<Vec<serde_json::Value>>>> {
    //获取到数据源
    let context = state.context.clone();
    //查询
    let (meta_datasource, datasource) = _get_datasources(&context, ds_id, datasource).await?;
    let res =
        batch_instance_query(context, &Some(meta_datasource), &datasource, items, options).await?;

    Ok(res)
}
